package com.laxcen.intelligenttoy;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.apkfuns.logutils.LogUtils;
import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.laxcen.intelligenttoy.BLE.BLEInstruct;
import com.laxcen.intelligenttoy.BLE.BLEParam;
import com.laxcen.intelligenttoy.BLE.BleConnectDialog;
import com.laxcen.intelligenttoy.BLE.DataUtils;
import com.laxcen.intelligenttoy.BLE.OpenBleProgreessDialog;
import com.laxcen.toydemo.BaseActivity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import io.reactivex.annotations.Nullable;

/**
 * 封装了Ble操作的activity
 * Created by wudi on 2020/6/9.
 */

public abstract class BLEActivity extends BaseActivity {
    protected BleManager mBleManager;//蓝牙管理者
    protected BleDevice mBleDevice;//当前BLE设备
    protected AppCompatActivity mActivity;
    private List<byte[]> byteArray = new ArrayList<>();//返回参数的缓存数据

    protected abstract void connectSuccess();//连接成功

    protected abstract void disConnect();//断开连接

    protected abstract void readAllSuccess(byte[] data);//读取所有标签成功

    /**
     * 将蓝牙数据解析为10个标签的List列表
     * 判断byte[]的长度 当长度为0时 代表无标签返回
     *
     * @param dataList
     */
    protected abstract void readAllSuccessToList(List<byte[]> dataList);

    protected abstract void onBleScanCallbackScanFinished();

    //扫描返回
    private BleScanCallback mBleScanCallBack = new BleScanCallback() {
        @Override
        public void onScanFinished(List<BleDevice> scanResultList) {
            LogUtils.d("mBleScanCallBack onScanFinished 扫描完成");
            //扫描时间结束
            BleConnectDialog.getInstance(BLEActivity.this).dismiss();
            onBleScanCallbackScanFinished();
        }

        @Override
        public void onScanStarted(boolean success) {
            LogUtils.d("mBleScanCallBack onScanStarted 扫描开始");
            if (success) {
//                OpenBleProgreessDialog.show(mActivity, "尝试连接托盘…\r\n 请确认托盘已通电源，并且开启蓝牙");
                BleConnectDialog.getInstance(BLEActivity.this).show("尝试连接托盘…\n请确认托盘已通电源，\r并且开启蓝牙");
            }
        }

        @Override
        public void onScanning(BleDevice bleDevice) {
            LogUtils.d("mBleScanCallBack onScanning 扫描到设备");
            //扫描到一个蓝牙设备后返回
            mBleManager.cancelScan();
            mBleManager.connect(bleDevice, mBleGattCallBack);
        }
    };

    protected abstract void onBleGattCallbackConnectFail();

    //连接回调
    private BleGattCallback mBleGattCallBack = new BleGattCallback() {
        @Override
        public void onStartConnect() {
            LogUtils.d("mBleGattCallBack onStartConnect 连接开始");
//            OpenBleProgreessDialog.show(mActivity, "连接中....");
            BleConnectDialog.getInstance(BLEActivity.this).show("连接中....");
        }

        @Override
        public void onConnectFail(BleDevice bleDevice, BleException exception) {
            LogUtils.d("mBleGattCallBack onConnectFail 连接失败");
            BleConnectDialog.getInstance(BLEActivity.this).dismiss();
            onBleGattCallbackConnectFail();
        }

        @Override
        public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
            LogUtils.d("mBleGattCallBack onConnectSuccess 连接成功");
            BleConnectDialog.getInstance(BLEActivity.this).dismiss();
            mBleDevice = bleDevice;
            connectSuccess();
            mBleManager.notify(mBleDevice, BLEParam.serviceUUID, BLEParam.NotifyUUID, mBleNotifyCallback);
        }

        @Override
        public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
            //断开连接回调，主动断开isActiveDisConnected为true
            LogUtils.d("mBleGattCallBack onDisConnected 连接断开");
            disConnect();
            mBleDevice = null;
        }
    };

    //写回调
    private BleWriteCallback mBleWriteCallback = new BleWriteCallback() {
        @Override
        public void onWriteSuccess(int current, int total, byte[] justWrite) {
        }

        @Override
        public void onWriteFailure(BleException exception) {
            LogUtils.d(exception);
            Toast.makeText(BLEActivity.this, "error" + exception.getCode() + exception.getDescription(), Toast.LENGTH_SHORT).show();
        }
    };

    //通知回调
    private BleNotifyCallback mBleNotifyCallback = new BleNotifyCallback() {
        @Override
        public void onNotifySuccess() {
            LogUtils.d("BleNotifyCallback onNotifySuccess 通知回调成功");
        }

        @Override
        public void onNotifyFailure(BleException exception) {
            Toast.makeText(mActivity, "标签指令数据返回失败", Toast.LENGTH_SHORT).show();
            LogUtils.d("BleNotifyCallback onNotifyFailure 通知回调失败");
            LogUtils.d(exception);
        }

        @Override
        public void onCharacteristicChanged(byte[] data) {
            LogUtils.d("***标签指令数据返回**");
            receivedData(data);
        }
    };

    /**
     * 获取到的蓝牙指令返回数据
     *
     * @param data
     */
    private void receivedData(byte[] data) {
        int length = data[2];//数据总长度的位置
        byteArray.add(data);
        String hex = DataUtils.byteArrayToHex(data);//数据转十六进制
        Log.d("receivedData", hex);
        int blength = 0;
        for (byte[] b : byteArray) {//已获得数据的长度
            blength += b.length - 3;
        }
        if (hex.indexOf("029") == 0) {
            //开天线成功
            LogUtils.d("天线切换成功！");
            byteArray.clear();
        } else if (hex.equalsIgnoreCase("03510100")) {
            showToast("写入成功");
            byteArray.clear();
        } else if (length == blength) {//数据标定长度与实际获得的长度相等时代表读取完毕
            LogUtils.d("***完整接收指令时间**" + System.currentTimeMillis());
            //结束
            byte[] mergeBytes = DataUtils.mergeBytes(byteArray, 3);//合并数据包
            byte[] realBytes = new byte[length];
            System.arraycopy(mergeBytes, 0, realBytes, 0, realBytes.length);
//            readAllSuccess(realBytes);
            toListSuccess(realBytes);
        } else {
            Log.d("数据传输中...", hex);
        }
    }

    private void toListSuccess(byte[] data) {
        List<byte[]> byteList = new ArrayList<>();
        int i = 0;
        while (i < data.length) {
            if (data[i] == -1) {
                //空的
                byteList.add(new byte[0]);
                i++;
            } else {
                byte[] bytes = new byte[8];
                System.arraycopy(data, i, bytes, 0, 8);
                byteList.add(bytes);
                i = i + 8;
            }
        }
        readAllSuccessToList(byteList);
    }

    /**
     * 读所有标签
     */
    protected void readTagAllLabel() {
        byteArray.clear();//清除之前的标签信息
        LogUtils.d("***发送读标签指令readTagAllLabel**" + System.currentTimeMillis());
        mBleManager.write(mBleDevice, BLEParam.serviceUUID, BLEParam.writeUUID
                , BLEInstruct.getReadAllLabel(), true, mBleWriteCallback);
    }

    /**
     * 读单个标签
     */
    protected void readSingleLabel(int antennaNum) {
        byteArray.clear();//清除之前的标签信息
        LogUtils.d("***发送读标签指令readSingleLabel**" + System.currentTimeMillis());
        mBleManager.write(mBleDevice, BLEParam.serviceUUID, BLEParam.writeUUID
                , BLEInstruct.getReadSingleLabel((byte) antennaNum), true, mBleWriteCallback);
    }

    /**
     * 写标签
     */
    protected void writeTag(String hexString, int antennaNum) {
        if (antennaNum == -1) {
            showToast("请先连接并切换天线！");
            return;
        }
        if (hexString.isEmpty()) {
            showToast("写入数据不能为空！");
            return;
        }
        byte[] bytes = new byte[17];
        byte[] strBytes = DataUtils.hexToByteArray(hexString);
        System.arraycopy(strBytes, 0, bytes, 0, strBytes.length);
        List<byte[]> byteArray = DataUtils.splitBytes(bytes,
                BLEInstruct.getWriteHead1());
        LogUtils.d(Arrays.toString(strBytes));
        for (byte[] bs : byteArray) {
            mBleManager.write(mBleDevice, BLEParam.serviceUUID, BLEParam.writeUUID
                    , bs, true, mBleWriteCallback);
        }
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initBLE();
        initScanRule();
    }

    /**
     * 切换天线
     */
    protected void cutAntenna(int antennaNum) {
        byteArray.clear();//清除之前的标签信息
        mBleManager.write(mBleDevice, BLEParam.serviceUUID, BLEParam.writeUUID
                , BLEInstruct.getCutAntenna((byte) (antennaNum)), true, mBleWriteCallback);
    }

    /**
     * 初始化蓝牙
     */
    private void initBLE() {
        mBleManager = BleManager.getInstance();
        mBleManager.init(getApplication());
        if (!mBleManager.isSupportBle()) {
            //当前设备不支持BLE功能
            Toast.makeText(this, "当前设备不支持BLE功能", Toast.LENGTH_SHORT).show();
            finish();
        } else {
            mBleManager.enableLog(true)//是否打印log
                    .setReConnectCount(1, 5000) //重连次数与间隔
                    .setOperateTimeout(5000);//设置超时时间
        }
    }

    /**
     * 初始化扫描规则
     */
    private void initScanRule() {
        BleScanRuleConfig config = new BleScanRuleConfig.Builder()
//                .setDeviceMac(BLEParam.macAddress)//指定设备mac地址
                .setDeviceName(false, BLEParam.deviceName)//指定设备广播名
                .setScanTimeOut(10000)//扫描超时时间
                .build();
        mBleManager.initScanRule(config);
    }

    /**
     * 连接操作
     */
    protected void connectBLE() {
        LogUtils.d("开始连接蓝牙");
        if (!mBleManager.isBlueEnable()) {
            //检查蓝牙是否打开
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, 0x01);
            return;
        }
        if (mBleDevice != null) {
            LogUtils.d("已有蓝牙链接，直接连接");
            //之前有连接就直接连接
            mBleManager.connect(mBleDevice, mBleGattCallBack);
        } else {
            LogUtils.d("没有蓝牙链接，开始扫描");
            //如果之前没有连接，先扫描
            mBleManager.scan(mBleScanCallBack);
        }
    }

    /**
     * 断开连接
     */
    protected void disconnectBLE() {
        if (mBleDevice != null) {
            mBleManager.disconnect(mBleDevice);
        } else {
            mBleManager.disconnectAllDevice();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mBleManager != null) {
            mBleManager.disconnectAllDevice();
            mBleManager.destroy();
        }
        BleConnectDialog.getInstance(BLEActivity.this).dismiss();
    }

    /**
     * 显示吐司
     *
     * @param msg
     */
    protected void showToast(String msg) {
        Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();
    }

    //设置字体为默认大小，不随系统字体大小改而改变
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (newConfig.fontScale != 1)//非默认值
            getResources();
        super.onConfigurationChanged(newConfig);
    }


    @Override
    public Resources getResources() {
        Resources res = super.getResources();
        if (res.getConfiguration().fontScale != 1) {//非默认值
            Configuration newConfig = new Configuration();
            newConfig.setToDefaults();//设置默认
            res.updateConfiguration(newConfig, res.getDisplayMetrics());
        }
        return res;
    }

}
